#include <stdlib.h>
#include <string.h>
#include "seqlist.h"

int seqlist_init(seqlist_t **mylist, int capacity, int size)
{
	seqlist_t *me = NULL;	

	// 顺序表结构
	me = malloc(sizeof(seqlist_t));
	if (NULL == me)
		return -1;

	// 数组
	me->arr = calloc(capacity, size);
	if (NULL == me->arr) {
		free(me);
		return -1;
	}
	// 容量
	me->capacity = capacity;
	// 每个元素的大小
	me->size = size;
	me->nmemb = 0;

	*mylist = me;

	return 0;
}

int seqlist_is_full(const seqlist_t *mylist)
{
	return mylist->nmemb == mylist->capacity;
}

int seqlist_insert(seqlist_t *mylist, const void *data)
{
	if (seqlist_is_full(mylist)) {
		mylist->arr = realloc(mylist->arr, (mylist->capacity + INCREACE_CNT) * mylist->size);
		if (NULL == mylist->arr)
			return -1;
		mylist->capacity += INCREACE_CNT;
	}
	memcpy((char *)mylist->arr + mylist->nmemb * mylist->size, data, mylist->size);
	mylist->nmemb++;

	return 0;
}

void *seqlist_find(const seqlist_t *mylist, const void *key, cmp_t cmp)
{
	int i;

	for (i = 0; i < mylist->nmemb; i++) {
		// int arr[3]; (char *)arr + i * sizeof(int)
		if (0 == cmp((char *)mylist->arr + i * mylist->size, key))
			return (char *)mylist->arr + i * mylist->size;
	}

	return NULL;
}

int seqlist_delete(seqlist_t *mylist, const void *key, cmp_t cmp)
{
	void *f = NULL;
	int del_pos, decrease;

	f = seqlist_find(mylist, key, cmp);
	if (NULL == f)
		return -1;
	// 要删除元素的地址在f
	del_pos = ((char *)f - (char *)mylist->arr) / mylist->size;
	// 覆盖
	memcpy(f, (char *)f + mylist->size, \
			(mylist->nmemb - (del_pos + 1)) * mylist->size);
	mylist->nmemb --;
	// 缩空间
	if ((mylist->capacity - mylist->nmemb) > INCREACE_CNT) {
		decrease = (mylist->capacity - mylist->nmemb) - INCREACE_CNT;
		mylist->capacity -= decrease;
		mylist->arr = realloc(mylist->arr, mylist->capacity * mylist->size);
		if (NULL == mylist->arr)
			return -1;
	}

	return 0;
}

void seqlist_traval(const seqlist_t *mylist, pri_t pri)
{
	int i;

	for (i = 0; i < mylist->nmemb; i++) {
		pri((char *)mylist->arr + i * mylist->size);
	}
}

void seqlist_destroy(seqlist_t **mylist)
{
	if (*mylist == NULL)
		return ;
	free((*mylist)->arr);
	(*mylist)->arr = NULL;
	free(*mylist);
	*mylist = NULL;
}

int seqlist_insert_sort(seqlist_t *mylist, const void *data, cmp_t cmp)
{
	int i;

	if (seqlist_is_full(mylist)) {
		mylist->arr = realloc(mylist->arr, (mylist->capacity + INCREACE_CNT) * mylist->size);
		if (NULL == mylist->arr)
			return -1;
		mylist->capacity += INCREACE_CNT;
	}
	// 找到合适的位置
	for (i = mylist->nmemb - 1; i >= 0; i--) {
		if (cmp((char *)mylist->arr + i * mylist->size, data) > 0) {
			// i元素大, 向后挪
			memmove((char *)mylist->arr + (i + 1) * mylist->size, \
					(char *)mylist->arr + i * mylist->size, mylist->size);
		} else 
			break;
	}

	memcpy((char *)mylist->arr + (i + 1) * mylist->size, data, mylist->size);
	mylist->nmemb++;

}

